﻿//LicenseHelper.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Licensing
{
	using System;
	using System.IO;
#if !DEBUG
	using System.Reflection;
	using System.Security.Cryptography.X509Certificates;
#endif

	using Ecng.Common;
	using Ecng.Security;

	using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
	using Strategies;

	/// <summary>
	/// Вспомагательный класс для работы с лицензиями.
	/// </summary>
	public static class LicenseHelper
	{
		private static readonly CryptoAlgorithm _algo;
		private const string _licenseFile = "stocksharp_license.xml";

		static LicenseHelper()
		{
			const string publicKey = "AQEBAQEBAAMAAAABAAEAgAAAAKqFr2tRjq8T9yeS6heDqbh6Nz+6tIizvCxfCkG0r4TEE61Cnccg9jedEuWEhFdzEVOz/LT/ySp7Tojph5RsZmN8QQ+utkbiywyjS27cglD/79IDUZ5NhLspXc/WAXzPlYCGLx2TfDEJgcGb9nktaHWwrpe588PHtj6Qfc7ReR7F";
			_algo = CryptoAlgorithm.Create(AlgorithmTypes.Asymmetric, ProtectedKey.CreateFromPlaintextKey(publicKey.Base64(), CryptoAlgorithm.DefaultScope), null);
		}

		private static string StockSharpFolder
		{
			get
			{
				return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "StockSharp");
			}
		}

		/// <summary>
		/// Текущая лицензия. Если лицензия не существует, то будет возвращено null.
		/// </summary>
		public static License CurrentLicense
		{
			get
			{
				License license;

				if (!File.Exists(_licenseFile))
				{
					var stockSharpFolder = StockSharpFolder;
					var myDocFile = Path.Combine(stockSharpFolder, _licenseFile);

					if (!File.Exists(myDocFile))
					{
						using (var client = new LicenseClient())
							license = client.GetTrialLicense();

						if (!Directory.Exists(stockSharpFolder))
							Directory.CreateDirectory(stockSharpFolder);

						File.WriteAllBytes(myDocFile, license.Body);
					}
					else
						license = new License(File.ReadAllBytes(myDocFile));
				}
				else
				{
					license = new License(File.ReadAllBytes(_licenseFile));
				}

				return license;
			}
		}

		private static License GetLicenseOrDownload()
		{
			var license = CurrentLicense;

			if (license == null)
			{
				var stockSharpFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "StockSharp");
				var myDocFile = Path.Combine(stockSharpFolder, _licenseFile);

				if (!File.Exists(myDocFile))
				{
					using (var client = new LicenseClient())
						license = client.GetTrialLicense();

					if (!Directory.Exists(stockSharpFolder))
						Directory.CreateDirectory(stockSharpFolder);

					File.WriteAllBytes(myDocFile, license.Body);
				}
				else
					license = new License(File.ReadAllBytes(myDocFile));
			}

			return license;
		}

		/// <summary>
		/// Получить оставшееся время действия лицензии.
		/// </summary>
		/// <param name="license">Лицензия.</param>
		/// <returns>Оставшееся время действия лицензии. Если лицензия истекла, то будет возвращено значение <see cref="TimeSpan.Zero"/>.</returns>
		public static TimeSpan GetEstimatedTime(this License license)
		{
			return TimeSpan.FromDays(100);
		}

		/// <summary>
		/// Проверить является ли лицензия временной.
		/// </summary>
		/// <param name="license">Лицензия.</param>
		/// <returns>True, если лицензия временная, иначе, false.</returns>
		public static bool IsTrial(this License license)
		{
			return false;
		}

		/// <summary>
		/// Проверить лицензию по типу функциональности.
		/// </summary>
		/// <param name="featureType">Тип функциональности.</param>
		/// <returns>True, если функциональность поддерживается, иначе, false.</returns>
		public static bool IsLicenseSupport(this Type featureType)
		{
			return true;
		}

		/// <summary>
		/// Проверить лицензию по названию функциональности.
		/// </summary>
		/// <param name="featureName">Название функциональности.</param>
		/// <returns>True, если функциональность поддерживается, иначе, false.</returns>
		public static bool IsLicenseSupport(this string featureName)
		{
			return true;
		}

		private static bool IsNoLicense()
		{
			return true;
#if DEBUG
			return true;
#else
			try
			{
				var appName = Assembly.GetEntryAssembly().ManifestModule.Name;
				var basicSigner = X509Certificate.CreateFromSignedFile(appName);
				var cert = new X509Certificate2(basicSigner);
				var pubKey = cert.PublicKey.EncodedKeyValue.Format(true);

				// для подписанных файлов не нужно делать проверку лицензий
				if (pubKey == "30 81 89 02 81 81 00 ac 88 25 69 0f f8 60 25 95 2c 5e 52 89 7f f0 86 d3 5f 7d 9b 9d 6f 2d 54 6d 2d 9b 0b 35 d9 b3 03 5c 8d 01 de d6 26 59 85 f1 f2 66 73 dc 9e 06 dd ed 91 60 09 5b 49 26 7f 07 40 53 60 29 a0 56 36 ad 94 bf 42 e2 9e 2c c9 7f 5d ff fb b8 f4 20 bf 51 65 ea ae 79 3a 54 10 17 c4 af 43 99 ee ff 5c e3 c3 61 3d 92 28 f0 77 d9 be 95 ca 68 2b 54 41 6a d5 18 14 58 87 21 1e 8f 7a 22 cf 53 ec eb 85 02 03 01 00 01")
					return true;
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.WriteLine(ex);
			}

			return false;
#endif
		}

		private static bool IsLicenseSupport(Func<License, bool> check)
		{
			return true;
		}

		/// <summary>
		/// Запустить проверку лицензии для стратегии.
		/// </summary>
		/// <param name="strategy">Стратегия, для котрого необходимо сделать проверку лицензии.</param>
		/// <returns>Описание ошибки проверки лицении.</returns>
		public static Exception StartValidation(this Strategy strategy)
		{
			return null;
		}

		/// <summary>
		/// Запустить проверку лицензии для функциональности.
		/// </summary>
		/// <param name="feature">Функциональность (может быть шлюзом, стратегий и т.д.).</param>
		/// <param name="failedAction">Действие, которое будет вызвано через 10 минут после ошибки проверки лицении и повторяться каждую минуту.</param>
		/// <returns>Описание ошибки проверки лицении.</returns>
		public static Exception StartValidation(this object feature, Action failedAction)
		{
			return null;
		}

		/// <summary>
		/// Сохранить лицензию на диске.
		/// </summary>
		/// <param name="license">Лицензия.</param>
		public static void Save(this License license)
		{
			if (license == null)
				throw new ArgumentNullException("license");

			File.WriteAllBytes(Path.Combine(StockSharpFolder, _licenseFile), license.Body);
		}
	}
}